/**
@file
Contains template functions wrapping corresponding c-style functions.

Version:
0.2.0

Last updated date:
2012-12-11

Created date:
2012-09-20
*/

#pragma once
#include <string.h>


namespace Zaf {
namespace String {


/**
Gets the length of string.

@param str C-style string.
@return The number of characters in \a str

This function is a wrapper fo strlen and wcslen.
*/
template<typename CharType>
unsigned int StrLen(const CharType* str);

template<>
inline unsigned int StrLen<char>(const char* str) {
	return strlen(str);
}

template<>
inline unsigned int StrLen<wchar_t>(const wchar_t* str) {
	return wcslen(str);
}



/**
Compares two strings.

@param str1 A c-style string.
@param str2 Another c-style string.
@return 
The return value equals to 0 if \a str1 identical to \a str2;
less than 0 if \a str1 less than \a str2;
greater than 0 if \a str1 greater than \a str2.

This function is a wrapper for strcmp and wcscmp.
*/
template<typename CharType>
int StrCmp(const CharType* str1, const CharType* str2);

template<>
inline int StrCmp<char>(const char* str1, const char* str2) {
	return strcmp(str1, str2);
}

template<>
inline int StrCmp<wchar_t>(const wchar_t* str1, const wchar_t* str2) {
	return wcscmp(str1, str2);
}



/**
Compares two strings, ignoring their case.

@param str1 A c-style string.
@param str2 Another c-style string.
@return 
The return value equals to 0 if \a str1 identical to \a str2;
less than 0 if \a str1 less than \a str2;
greater than 0 if \a str1 greater than \a str2.

This function is a wrapper for _stricmp and _wcsicmp.
*/
template<typename CharType>
int StrICmp(const CharType* str1, const CharType* str2);

template<>
inline int StrICmp<char>(const char* str1, const char* str2) {
	return _stricmp(str1, str2);
}

template<>
inline int StrICmp<wchar_t>(const wchar_t* str1, const wchar_t* str2) {
	return _wcsicmp(str1, str2);
}



/**
Compares two strings' substring.

@param str1 A c-style string.
@param str2 Another c-style string.
@param count The length of substring.
@return 
The return value equals to 0 if \a str1 substring identical to \a str2 substring;
less than 0 if \a str1 substring less than \a str2 substring;
greater than 0 if \a str1 substring greater than \a str2 substring.

This function is a wrapper for strncmp and wcsncmp.
*/
template<typename CharType>
int StrNCmp(const CharType* str1, const CharType* str2, unsigned int count);

template<>
inline int StrNCmp<char>(const char* str1, const char* str2, unsigned int count) {
	return strncmp(str1, str2, count);
}

template<>
inline int StrNCmp<wchar_t>(const wchar_t* str1, const wchar_t* str2, unsigned int count) {
	return wcsncmp(str1, str2, count);
}



/**
Compares two strings' substring, ignoring their case.

@param str1 A c-style string.
@param str2 Another c-style string.
@param count The length of substring.
@return 
The return value equals to 0 if \a str1 substring identical to \a str2 substring;
less than 0 if \a str1 substring less than \a str2 substring;
greater than 0 if \a str1 substring greater than \a str2 substring.

This function is a wrapper for _strnicmp and _wcsnicmp.
*/
template<typename CharType>
int StrNICmp(const CharType* str1, const CharType* str2, unsigned int count);

template<>
inline int StrNICmp<char>(const char* str1, const char* str2, unsigned int count) {
	return _strnicmp(str1, str2, count);
}

template<>
inline int StrNICmp<wchar_t>(const wchar_t* str1, const wchar_t* str2, unsigned int count) {
	return _wcsnicmp(str1, str2, count);
}



/**
Finds the first occurrence of specified character in string.

@param str C-style string.
@param ch Character to be found.
@return 
A pointer to the first occurrence of \a ch in \a str, 
NULL if \a ch is not found.

This function is a wrapper for strchr and wcschr.
*/
template<typename CharType>
const CharType* StrChr(const CharType* str, CharType ch);

template<>
inline const char* StrChr<char>(const char* str, char ch) {
	return strchr(str, ch);
}

template<>
inline const wchar_t* StrChr<wchar_t>(const wchar_t* str, wchar_t ch) {
	return wcschr(str, ch);
}



/**
This is an overload version of StrChr.
@see StrChr
*/
template<typename CharType>
CharType* StrChr(CharType* str, CharType ch);

template<>
inline char* StrChr<char>(char* str, char ch) {
	return strchr(str, ch);
}

template<>
inline wchar_t* StrChr<wchar_t>(wchar_t* str, wchar_t ch) {
	return wcschr(str, ch);
}



/**
Finds the last occurrence of specified character in string.

@param str C-style string.
@param ch Character to be found.
@return 
A pointer to the last occurrence of \a ch in \a str, 
NULL if \a ch is not found.

This function is a wrapper for strrchr and wcsrchr.
*/
template<typename CharType>
const CharType* StrRChr(const CharType* str, CharType ch);

template<>
inline const char* StrRChr<char>(const char* str, char ch) {
	return strrchr(str, ch);
}

template<>
inline const wchar_t* StrRChr<wchar_t>(const wchar_t* str, wchar_t ch) {
	return wcsrchr(str, ch);
}



/**
This is an overload version of StrRChr.
@see StrRChr
*/
template<typename CharType>
CharType* StrRChr(CharType* str, CharType ch);

template<>
inline char* StrRChr<char>(char* str, char ch) {
	return strrchr(str, ch);
}

template<>
inline wchar_t* StrRChr<wchar_t>(wchar_t* str, wchar_t ch) {
	return wcsrchr(str, ch);
}



/**
Finds the first occurrence of specified string in string.

@param str C-style string.
@param searchStr C-style string to be found.
@return 
A pointer to the first occurrence of \a searchStr in \a str,
NULL if \a searchStr is not found.

This function is a wrapper for strstr and wcsstr.
*/
template<typename CharType>
const CharType* StrStr(const CharType* str, const CharType* searchStr);

template<>
inline const char* StrStr<char>(const char* str, const char* searchStr) {
	return strstr(str, searchStr);
}

template<>
inline const wchar_t* StrStr<wchar_t>(const wchar_t* str, const wchar_t* searchStr) {
	return wcsstr(str, searchStr);
}


/**
This is a overload version of StrStr.
@see StrStr
*/
template<typename CharType>
CharType* StrStr(CharType* str, const CharType* searchStr);

template<>
inline char* StrStr<char>(char* str, const char* searchStr) {
	return strstr(str, searchStr);
}

template<>
inline wchar_t* StrStr<wchar_t>(wchar_t* str, const wchar_t* searchStr) {
	return wcsstr(str, searchStr);
}



/**
Converts a string to long.

@param str C-style string to be converted.
@param endPtr Pointer to character that stopps scan.
@param radix The radix of number to use.
@return A long value represented by \a str.

This function is a wrapper for strtol and wcstol.
*/
template<typename CharType>
long StrToLong(const CharType* str, CharType** endPtr, int radix);

template<>
inline long StrToLong<char>(const char* str, char** endPtr, int radix) {
	return strtol(str, endPtr, radix);
}

template<>
inline long StrToLong<wchar_t>(const wchar_t* str, wchar_t** endPtr, int radix) {
	return wcstol(str, endPtr, radix);
}



/**
Converts a string to unsigned long.

@param str C-style string to be converted.
@param endPtr Pointer to character that stopps scan.
@param radix The radix of number to use.
@return An unsigned long value represented by \a str.

This function is a wrapper for strtoul and wcstoul.
*/
template<typename CharType>
unsigned long StrToULong(const CharType* str, CharType** endPtr, int radix);

template<>
inline unsigned long StrToULong<char>(const char* str, char** endPtr, int radix) {
	return strtoul(str, endPtr, radix);
}

template<>
inline unsigned long StrToULong<wchar_t>(const wchar_t* str, wchar_t** endPtr, int radix) {
	return wcstoul(str, endPtr, radix);
}



/**
Converts a string to long long.

@param str C-style string to be converted.
@param endPtr Pointer to character that stopps scan.
@param radix The radix of number to use.
@return A long long value represented by \a str.

This function is a wrapper for _strtoi64 and _wcstoi64.
*/
template<typename CharType>
long long StrToLLong(const CharType* str, CharType** endPtr, int radix);

template<>
inline long long StrToLLong<char>(const char* str, char** endPtr, int radix) {
	return _strtoi64(str, endPtr, radix);
}

template<>
inline long long StrToLLong<wchar_t>(const wchar_t* str, wchar_t** endPtr, int radix) {
	return _wcstoi64(str, endPtr, radix);
}



/**
Converts a string to unsigned long long.

@param str C-style string to be converted.
@param endPtr Pointer to character that stopps scan.
@param radix The radix of number to use.
@return An unsigned long long value represented by \a str.

This function is a wrapper for _strtoui64 and _wcstoui64.
*/
template<typename CharType>
unsigned long long StrToULLong(const CharType* str, CharType** endPtr, int radix);

template<>
inline unsigned long long StrToULLong<char>(const char* str, char** endPtr, int radix) {
	return _strtoui64(str, endPtr, radix);
}

template<>
inline unsigned long long StrToULLong<wchar_t>(const wchar_t* str, wchar_t** endPtr, int radix) {
	return _wcstoui64(str, endPtr, radix);
}



/**
Converts a long value to string.

@param value Long value to be converted.
@param str %Buffer to preserve the result.
@param sizeOfstr The length of buffer.
@param radix The radix of number to use.
@return Error code.

This function is a wrapper for _ltoa_s and _ltow_s.
*/
template<typename CharType>
errno_t LongToStr(long value, CharType* str, size_t sizeOfstr, int radix);

template<>
inline errno_t LongToStr<char>(long value, char* str, size_t sizeOfstr, int radix) {
	return _ltoa_s(value, str, sizeOfstr, radix);
}

template<>
inline errno_t LongToStr<wchar_t>(long value, wchar_t* str, size_t sizeOfstr, int radix) {
	return _ltow_s(value, str, sizeOfstr, radix);
}



/**
Converts an unsigned long value to string.

@param value Unsigned long value to be converted.
@param str %Buffer to preserve the result.
@param sizeOfstr The length of buffer.
@param radix The radix of number to use.
@return Error code.

This function is a wrapper for _ultoa_s and _ultow_s.
*/
template<typename CharType>
errno_t ULongToStr(unsigned long value, CharType* str, size_t sizeOfstr, int radix);

template<>
inline errno_t ULongToStr<char>(unsigned long value, char* str, size_t sizeOfstr, int radix) {
	return _ultoa_s(value, str, sizeOfstr, radix);
}

template<>
inline errno_t ULongToStr<wchar_t>(unsigned long value, wchar_t* str, size_t sizeOfstr, int radix) {
	return _ultow_s(value, str, sizeOfstr, radix);
}



/**
Converts a long long value to string.

@param value Long long value to be converted.
@param str %Buffer to preserve the result.
@param sizeOfstr The length of buffer.
@param radix The radix of number to use.
@return Error code.

This function is a wrapper for _i64toa_s and _i64tow_s.
*/
template<typename CharType>
errno_t LLongToStr(long long value, CharType* str, size_t sizeOfstr, int radix);

template<>
inline errno_t LLongToStr<char>(long long value, char* str, size_t sizeOfstr, int radix) {
	return _i64toa_s(value, str, sizeOfstr, radix);
}

template<>
inline errno_t LLongToStr<wchar_t>(long long value, wchar_t* str, size_t sizeOfstr, int radix) {
	return _i64tow_s(value, str, sizeOfstr, radix);
}



/**
Converts an unsigned long long value to string.

@param value Unsigned long long value to be converted.
@param str %Buffer to preserve the result.
@param sizeOfstr The length of buffer.
@param radix The radix of number to use.
@return Error code.

This function is a wrapper for _ui64toa_s and _ui64tow_s.
*/
template<typename CharType>
errno_t ULLongToStr(unsigned long long value, CharType* str, size_t sizeOfstr, int radix);

template<>
inline errno_t ULLongToStr<char>(unsigned long long value, char* str, size_t sizeOfstr, int radix) {
	return _ui64toa_s(value, str, sizeOfstr, radix);
}

template<>
inline errno_t ULLongToStr<wchar_t>(unsigned long long value, wchar_t* str, size_t sizeOfstr, int radix) {
	return _ui64tow_s(value, str, sizeOfstr, radix);
}



/**
Determines whether the specified character is a blank character.

@param ch Character to be determined.
@return Non-zero if \a ch is a blank character, 0 otherwise.

This function is a wrapper for isspace and iswspace.
*/
template<typename CharType>
int IsSpace(CharType ch);

template<>
inline int IsSpace<char>(char ch) {
	return isspace(ch);
}

template<>
inline int IsSpace<wchar_t>(wchar_t ch) {
	return iswspace(ch);
}



/**
Converts a string to lowercase.

@param str C-style string to be converted.
@param length The length of string.
@return Error code.

This function is a wrapper for _strlwr_s and _wcslwr_s.
*/
template<typename CharType>
errno_t StrLwr(CharType* str, size_t length);

template<>
inline errno_t StrLwr<char>(char* str, size_t length) {
	return _strlwr_s(str, length);
}

template<>
inline errno_t StrLwr<wchar_t>(wchar_t* str, size_t length) {
	return _wcslwr_s(str, length);
}



/**
Converts a string to uppercase.

@param str C-style string to be converted.
@param length The length of string.
@return Error code.

This function is a wrapper for _strupr_s and _wcsupr_s.
*/
template<typename CharType>
errno_t StrUpr(CharType* str, size_t length);

template<>
inline errno_t StrUpr<char>(char* str, size_t length) {
	return _strupr_s(str, length);
}

template<>
inline errno_t StrUpr<wchar_t>(wchar_t* str, size_t length) {
	return _wcsupr_s(str, length);
}

}
}